﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace 引用和值类型
{
    class Program
    {
        static void Main(string[] args)
        {
            Utils.OneBox();

            Console.WriteLine("新的Boxed例子");

            Point p1 = new Point(10, 10);
            Point p2 = new Point(20, 20);

            //调用ToString虚方法，不会装箱
            Console.WriteLine(p1.ToString());

            //调用GetType（一个虚方法）时，要对p进行装箱
            Console.WriteLine(p1.GetType());

            //When first call CompareTo() ,never boxing p
            //for call Co9mpareTo(Point), p2 is not boxed
            Console.WriteLine(p1.CompareTo(p2));//显示“-1”

            //p1要进行装箱，将引用放到c中
            IComparable c = p1;
            Console.WriteLine(c.GetType());//显示“Point”

            //第二次调用ComparaTo时，p1不需要装箱
            //由于向CompareTo 传递的不是一个Point变量
            //所以会调用CompareTo(Object),它要求获取对一个已经装箱Point的引用
            //c不会装箱，因为他引用的本来就是一个已经装箱的Point
            Console.WriteLine(p1.CompareTo(c));
            //显示“0”
            
            //第三次调用CompareTo时，c不需要装箱，因为它引用的本来就是一个装箱的Point
            //P2会装箱，因为调用的是CompareTo(Object)
            Console.WriteLine(c.CompareTo(p2));//显示“-1”

            //对c进行拆箱，字段复制到p2中
            p2 = (Point)c;
            //证明字段已经复制到p2中
            Console.WriteLine(p2.ToString());//显示“（10,10）”

            Console.WriteLine("新的例子:修改值类型的字段and使用接口修改值类型的字段");

            Point p3 = new Point(1, 1);
            Object o3=p3;
            myRenferance.Point p4 = new myRenferance.Point(2, 2);
            myRenferance.IChangeBoxedPoint o4=p4;
            p3.Change(5, 5);
            ((Point)o3).Change(5,5);
            p4.Change(5,5);
            //((myRenferance.Point)o4).Change(5,5);
            o4.Change(5, 5);
            Console.WriteLine("Without interface:\nValueType:{0}\nReferenceType:{1}", p3, o3);
            Console.WriteLine("With interface:\nValueType:{0}\nReferenceType:{1}", p4, o4);

            Console.ReadKey();
        }
    }
}
